package io.github.cocoa.module.socket.core.run;

import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIONamespace;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.protocol.Packet;
import com.corundumstudio.socketio.store.pubsub.DispatchMessage;
import com.corundumstudio.socketio.store.pubsub.PubSubStore;
import com.corundumstudio.socketio.store.pubsub.PubSubType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Netty Socket IO 服务器运行程序
 *
 * @author Chim
 * @since 2024/12/12
 */
@Slf4j
@Component
@Order(1)
public class NettySocketIoServerRunner implements CommandLineRunner {

    @Resource
    private SocketIOServer socketIOServer;
    @Resource
    private PubSubStore pubSubStore;
    @Resource
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Override
    public void run(String... args) {
        log.info("# >>> socketIOServer 启动");
        socketIOServer.start();

        // 注册 Nacos
        registerNacos();
        // 订阅消息
        subscribe();
    }

    /**
     * 注册 Nacos
     */
    private void registerNacos() {
        String serviceName = SpringUtil.getApplicationName() + "-socket-io";
        int port = socketIOServer.getConfiguration().getPort();
        try {
            NamingService namingService = NamingFactory.createNamingService(nacosDiscoveryProperties.getNacosProperties());

            // 注册 Nacos
            Instance instance = new Instance();
            instance.setIp(NetUtil.getLocalhostStr());
            instance.setPort(port);
            instance.setServiceName(serviceName);
            instance.setWeight(1.0);
            Map<String, String> map = new HashMap<>();
            map.put("preserved.register.source", "SPRING_CLOUD");
            instance.setMetadata(map);

            namingService.registerInstance(serviceName, instance);

            log.info("# >>> socket-io register Nacos success");
        } catch (NacosException e) {
            log.error("# >>> socket-io register Nacos error: {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 订阅消息
     */
    private void subscribe() {
        pubSubStore.subscribe(PubSubType.DISPATCH, message -> {
            Collection<SocketIOClient> clients = null;
            String room = message.getRoom();
            String namespace = message.getNamespace();
            Packet packet = message.getPacket();
            Object data = packet.getData();
            log.info("@subscribe data: {}", data);
            if (StrUtil.isNotBlank(namespace)) {
                SocketIONamespace socketIONamespace = socketIOServer.getNamespace(namespace);
                if (StrUtil.isBlank(room)) {
                    clients = socketIONamespace.getRoomOperations(room).getClients();
                }
            } else {
                clients = socketIOServer.getBroadcastOperations().getClients();
            }
        }, DispatchMessage.class);
    }

}
